package edu.gdit.health.service.impl;

import edu.gdit.health.base.result.Results;
import edu.gdit.health.dao.SysReportCountDao;
import edu.gdit.health.dao.SysReportDao;
import edu.gdit.health.model.SysReport;
import edu.gdit.health.model.SysReportCount;
import edu.gdit.health.model.bean.SysDict;
import edu.gdit.health.model.vo.SysReportCountVO;
import edu.gdit.health.service.SysReportService;
import edu.gdit.health.utils.StrUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysReportServiceImpl implements SysReportService {

    @Resource
    SysReportDao sysReportDao;

    @Resource
    SysReportCountDao sysReportCountDao;


    @Override
    public Map<String, ArrayList> getDictSet() {
        Map<String, ArrayList> rs = new HashMap<>();
        rs.put("temperature", new ArrayList<SysDict>());
        rs.put("travel", new ArrayList<SysDict>());
        rs.put("physical_condition", new ArrayList<SysDict>());
        rs.get("temperature").add(new SysDict("NORMAL" , "正常 37.3℃ 以下"));
        rs.get("temperature").add(new SysDict("LOW" , "低热 37.3-37.9℃"));
        rs.get("temperature").add(new SysDict("MIDDLE" , "中热 38-39℃"));
        rs.get("temperature").add(new SysDict("HIGH" , "高热 39℃以上"));
        rs.get("travel").add(new SysDict("1" , "有旅游"));
        rs.get("travel").add(new SysDict("0" , "没有旅游"));
        rs.get("physical_condition").add(new SysDict("travel" , "14天内曾居住或前往疫情高发地"));
        rs.get("physical_condition").add(new SysDict("contact" , "两周内有与确诊患者接触"));
        rs.get("physical_condition").add(new SysDict("normal" , "没有出现症状"));
        rs.get("physical_condition").add(new SysDict("rheum" , "感冒样症状：乏力、精神差、咳嗽、发烧、肌肉痛、头痛"));
        rs.get("physical_condition").add(new SysDict("polypnea" , "喘憋、呼吸急促"));
        rs.get("physical_condition").add(new SysDict("vomiting" , "恶心呕吐、腹泻"));
        rs.get("physical_condition").add(new SysDict("flustered" , "心慌、胸闷"));
        rs.get("physical_condition").add(new SysDict("conjunctivitis" , "结膜炎（红眼病样表现：眼睛涩、红、分泌物）"));
        return rs;
    }

    @Override
    public Results save(SysReport report) {
        report.setUserId(1L);
        return Results.success(sysReportDao.save(report));
    }

    private final int temperatureThresholdValue = 10;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    private final String  count = "count";
    private final String  temperature = "temperature";
    private final String  travel = "travel";
    private final String  physicalCondition = "physical_condition";
    private final String name = "name";
    private final  String value = "value";
    @Override
    public long countTemperatureLineData() {
        String startDateStr = sdf.format(new Date());
        String secondDate = sdf.format(getDay(1, new Date()));
        String temp = StrUtil.covertToQueryIn("HIGH", "MIDDLE");
        long flag = sysReportCountDao.sumValueByType("temperature", startDateStr, temp);
        long secondFlag = sysReportCountDao.sumValueByType("temperature", secondDate, temp);
        if (flag == 0) {
            return 0;
        }
        if (flag - secondFlag >= temperatureThresholdValue) {
            return flag;
        }
        return 0;
    }

    @Override
    public long countTemperatureData() {
        String startDateStr = sdf.format(new Date());
        return sysReportCountDao.sumValueByType("temperature", startDateStr, StrUtil.covertToQueryIn("HIGH", "MIDDLE"));
    }

    @Override
    public long countTravelData() {
        String startDateStr = sdf.format(new Date());
        return sysReportCountDao.sumValueByType("travel", startDateStr, StrUtil.covertToQueryIn("3", "2"));
    }

    @Override
    public long countPhysicalConditionData() {
        String startDateStr = sdf.format(new Date());
        return sysReportCountDao.sumValueByType("physical_condition", startDateStr, StrUtil.covertToQueryIn("contact", "rheum"));
    }

    @Override
    public void countReportData(Date now) {
        System.out.println("countReportData ... " + now.toString());
        String startDate, endDate;
        startDate = endDate = sdf.format(now);
        List<Map<String, Object>> temperatureData = sysReportDao.getChartTemperatureData(startDate, endDate);
        List<Map<String, Object>> travelData = sysReportDao.getChartTravelData(startDate, endDate);
        List<Map<String, Object>> countData = sysReportDao.getChartCountData(startDate, endDate);
        Map<String, Object> physicalConditionData = sysReportDao.getChartPhysicalConditionData(startDate, endDate);

        List<SysReportCount> list = new ArrayList();

        setData(temperatureData, list, temperature);
        setData(travelData, list, travel);
        setData(countData, list, count);
        if (physicalConditionData != null) {
            for (String key : physicalConditionData.keySet()) {
                SysReportCount count = new SysReportCount();
                count.setName(key);
                count.setValue(physicalConditionData.get(key).toString());
                count.setType(physicalCondition);
                list.add(count);
            }
        }

        for (SysReportCount item : list) {
            item.setCreateTime(new Date());
            item.setReportDate(startDate);
            sysReportCountDao.delete(item);
            sysReportCountDao.save(item);
        }
    }

    @Override
    public Results refresh() {
        this.countReportData(new Date());
        return Results.success();
    }

    @Override
    public Results getChartTemperatureLine(Date startDate, Date endDate, Integer past) {
        String startDateStr = sdf.format(startDate);
        String endDateStr = sdf.format(endDate);
        List<SysReportCount> data = sysReportCountDao.query(temperature ,startDateStr, endDateStr);

        List<SysReportCount> normalData = data.stream().filter(item->"NORMAL".equals(item.getName())).collect(Collectors.toList());
        List<SysReportCount> lowData = data.stream().filter(item->"LOW".equals(item.getName())).collect(Collectors.toList());
        List<SysReportCount> middleData = data.stream().filter(item->"MIDDLE".equals(item.getName())).collect(Collectors.toList());
        List<SysReportCount> highData = data.stream().filter(item->"HIGH".equals(item.getName())).collect(Collectors.toList());

        normalData = setDefaultLineData(normalData, endDate, past);
        lowData = setDefaultLineData(lowData, endDate, past);
        middleData = setDefaultLineData(middleData, endDate, past);
        highData = setDefaultLineData(highData, endDate, past);

        Map<String, List> rs = new HashMap<>();
        rs.put("NORMAL", normalData);
        rs.put("LOW", lowData);
        rs.put("MIDDLE", middleData);
        rs.put("HIGH", highData);
        return Results.success(rs);
    }

    @Override
    public Results getChartTemperatureData(String startDateStr, String endDateStr) {
        List<SysReportCount> data = sysReportCountDao.query(temperature, startDateStr, endDateStr);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, temperature);
        return Results.success(rs);
    }

    @Override
    public Results getChartTravelData(String startDateStr, String endDateStr) {
        List<SysReportCount> data = sysReportCountDao.query(travel, startDateStr, endDateStr);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, travel);
        return Results.success(rs);
    }

    @Override
    public Results getChartPhysicalConditionData(String startDateStr, String endDateStr) {
        List<SysReportCount> data = sysReportCountDao.query(physicalCondition, startDateStr, endDateStr);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, physicalCondition);
        return Results.success(rs);
    }

    private Date getDay(int past, Date startPoint) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startPoint);
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
        return calendar.getTime();
    }

    private List<SysReportCount> setDefaultLineData(List<SysReportCount> list, Date startDate, int past){
        Map<String, SysReportCount> data = list.stream().collect(Collectors.toMap(SysReportCount::getReportDate,item->item));
        List<SysReportCount> rs = new ArrayList<>();
        for (int i = past - 1; i >= 0; i--) {
            Date firstDate = getDay(i, startDate);
            String firstDateStr = sdf.format(firstDate);
            if (data.containsKey(firstDateStr)) {
                rs.add(data.get(firstDateStr));
            } else {
                SysReportCount sysReportCount = new SysReportCount();
                sysReportCount.setReportDate(firstDateStr);
                sysReportCount.setValue("0");
                rs.add(sysReportCount);
            }
        }
        return rs;
    }

    private void setData(List<Map<String, Object>> data, List list, String type){
        for (Map<String, Object> map : data) {
            if (map == null || !map.containsKey(name) || !map.containsKey(value)) {
                continue;
            }
            SysReportCount count = new SysReportCount();
            count.setName(map.get(name).toString());
            count.setValue(map.get(value).toString());
            count.setType(type);
            list.add(count);
        }
    }

    private void transData(List<SysReportCount> data, List<SysReportCountVO> target, String type){
        Map<String, String> map = new HashMap<>();
        if (null != type) {
            map = getDict(type);
        }
        for (SysReportCount item : data ) {
            SysReportCountVO vo = new SysReportCountVO();
            BeanUtils.copyProperties(item, vo);
            if (null != type && map.containsKey(item.getName())) {
                vo.setLabel(map.get(item.getName()));
            }
            target.add(vo);
        }
    }

    private Map<String, String> getDict(String type) {
        Map<String, String> map = new HashMap<>();
        if (temperature.equals(type)) {
            map.put("NORMAL", "正常 37.3℃ 以下");
            map.put("LOW", "低热 37.3-37.9℃");
            map.put("MIDDLE", "中热 38-39℃");
            map.put("HIGH", "高热 39℃以上");
            return map;
        }
        if (travel.equals(type)) {
            map.put("0", "近期没有出行");
            map.put("1", "去过低风险地区");
            map.put("2", "去过中风险地区");
            map.put("3", "去过高风险地区");
            return map;
        }
        if (physicalCondition.equals(type)) {
            map.put("travel", "14天内曾居住或前往疫情高发地");
            map.put("contact", "两周内有与确诊患者接触");
            map.put("normal", "没有出现症状");
            map.put("rheum", "感冒样症状：乏力、精神差、咳嗽、发烧、肌肉痛、头痛");
            map.put("polypnea", "喘憋、呼吸急促");
            map.put("vomiting", "恶心呕吐、腹泻");
            map.put("flustered", "心慌、胸闷");
            map.put("conjunctivitis", "结膜炎（红眼病样表现：眼睛涩、红、分泌物）");
            return map;
        }
        return map;
    }
}
